# -*- coding: utf-8 -*-
"""
实体匹配 API 路由

提供水利实体的快速匹配服务，基于 Trie 树实现
前端高频调用接口，响应时间 < 1ms

@author: zhulan
"""

import sys
from pathlib import Path
from typing import List, Optional, TYPE_CHECKING

from fastapi import APIRouter, Query
from fastapi.responses import ORJSONResponse
from pydantic import BaseModel, Field

# 添加 src 到路径（运行时）
_src_path = str(Path(__file__).resolve().parent.parent)
if _src_path not in sys.path:
    sys.path.insert(0, _src_path)

# noinspection PyUnresolvedReferences
from services.hydro_entity_matcher import HydroEntityMatcher  # noqa: E402

# ==================== 单例匹配器 ====================

_matcher: Optional[HydroEntityMatcher] = None


def get_matcher() -> HydroEntityMatcher:
    """获取全局匹配器实例（单例）"""
    global _matcher
    if _matcher is None:
        raise RuntimeError("实体匹配器未初始化，请先调用 init_matcher()")
    return _matcher


def init_matcher(csv_path: Optional[str] = None) -> HydroEntityMatcher:
    """
    初始化全局匹配器（服务启动时调用）
    
    Args:
        csv_path: CSV 文件路径，默认使用 src/data/hydro_entities.csv
    
    Returns:
        初始化后的匹配器实例
    """
    global _matcher
    
    if _matcher is not None:
        return _matcher
    
    _matcher = HydroEntityMatcher()
    
    # 默认 CSV 路径
    if csv_path is None:
        csv_path = str(Path(__file__).parent.parent / "data" / "hydro_entities.csv")
    
    count = _matcher.load_from_csv(csv_path)
    print(f"✅ 实体匹配器初始化完成，加载 {count} 个实体")
    
    return _matcher


# ==================== API 模型 ====================

class EntityMatch(BaseModel):
    """单个匹配结果"""
    name: str = Field(..., description="实体名称")
    type: str = Field(..., description="实体类型 (RESERVOIR/RIVER/STATION)")
    code: str = Field(..., description="实体编码")
    match_type: str = Field(..., description="匹配方式 (exact/alias/prefix/pinyin/shouzimu/fuzzy)")
    score: float = Field(..., ge=0, le=1, description="匹配分数 0-1")


class MatchResponse(BaseModel):
    """匹配响应"""
    query: str = Field(..., description="用户输入")
    count: int = Field(..., description="匹配数量")
    matches: List[EntityMatch] = Field(default_factory=list, description="匹配结果列表")


class SingleMatchResponse(BaseModel):
    """单个匹配响应（供前端使用）"""
    query: str = Field(..., description="用户输入")
    match: Optional[EntityMatch] = Field(None, description="匹配结果，无匹配时为 null")


class MatchErrorResponse(BaseModel):
    """错误响应"""
    error: str
    detail: str


# ==================== 路由 ====================

router = APIRouter(
    prefix="/api/entity",
    tags=["实体匹配"],
    responses={
        200: {"model": MatchResponse},
        500: {"model": MatchErrorResponse}
    }
)


@router.get(
    "/match",
    response_model=MatchResponse,
    response_class=ORJSONResponse,
    summary="实体匹配",
    description="""
    根据用户输入匹配水利实体
    
    支持的匹配方式（按优先级）：
    1. **别名精确匹配** (score=1.0) - 如 "尼尔基" → "尼尔基水库"
    2. **汉字精确匹配** (score=1.0) - 如 "尼尔基水库" → "尼尔基水库"
    3. **汉字前缀匹配** (score=0.9) - 如 "尼尔" → "尼尔基水库"
    4. **拼音精确匹配** (score=0.95) - 如 "nierji" → "尼尔基水库"
    5. **拼音前缀匹配** (score=0.85) - 如 "nier" → "尼尔基水库"
    6. **首字母匹配** (score=0.8) - 如 "nejsk" → "尼尔基水库"
    7. **模糊匹配** (score≤0.7) - 基于编辑距离
    
    **性能**: 响应时间 < 1ms，适合前端实时调用
    """
)
async def match_entity(
    q: str = Query(..., min_length=1, max_length=50, description="查询关键词"),
    limit: int = Query(5, ge=1, le=20, description="最大返回数量")
) -> MatchResponse:
    """
    匹配水利实体
    
    - **q**: 用户输入的关键词（支持汉字、拼音、首字母）
    - **limit**: 最大返回结果数，默认 5
    """
    matcher = get_matcher()
    results = matcher.match(q, max_results=limit)
    
    # 去重（按 name）
    seen = set()
    unique_results = []
    for r in results:
        if r['name'] not in seen:
            seen.add(r['name'])
            unique_results.append(EntityMatch(
                name=r['name'],
                type=r['type'],
                code=r['code'],
                match_type=r['match_type'],
                score=round(r['score'], 2)
            ))
    
    return MatchResponse(
        query=q,
        count=len(unique_results),
        matches=unique_results
    )


@router.get(
    "/suggest",
    response_model=SingleMatchResponse,
    response_class=ORJSONResponse,
    summary="输入联想",
    description="前缀匹配，返回最匹配的单个实体，供前端使用"
)
async def suggest_entity(
    prefix: str = Query(..., min_length=1, max_length=50, description="输入前缀")
) -> SingleMatchResponse:
    """
    输入联想（前缀匹配）
    
    专为前端设计，返回单个最匹配的实体
    """
    matcher = get_matcher()
    
    # 使用高性能单结果搜索，找到即返回，不遍历整个子树
    r = matcher.trie_hanzi.prefix_search_first(prefix)
    
    match = EntityMatch(
        name=r['name'],
        type=r['type'],
        code=r['code'],
        match_type='prefix',
        score=0.9
    ) if r else None
    
    return SingleMatchResponse(
        query=prefix,
        match=match
    )


@router.get(
    "/stats",
    summary="匹配器统计",
    description="返回当前加载的实体统计信息"
)
async def matcher_stats():
    """获取匹配器统计信息"""
    matcher = get_matcher()
    
    # 统计各类型实体数量
    type_counts = {}
    for entity in matcher.all_entities:
        t = entity['type']
        type_counts[t] = type_counts.get(t, 0) + 1
    
    return {
        "total_entities": len(matcher.all_entities),
        "alias_count": len(matcher.alias_map),
        "type_distribution": type_counts
    }

